//! # loader
//!
//! 第三方包加载器
//!
//! sgs_runtime 本身不实现任何运行包
//!
//! 可以参考 [sgs_pkg_std] 对标准包的实现

use crate::{
    error::PackageNotFoundError,
    pkg::{Package, Provide},
};

/// Loader
///
/// 第三方包加载器
#[derive(Debug, Default)]
pub struct Loader {
    /// 加载的使用第三方包
    pub packages: Vec<Package>,
}

impl Loader {
    /// 创建一个新的 Loader
    pub fn new() -> Self {
        Default::default()
    }

    /// 检查 package
    ///
    /// 如果武将数量不足，直接 panic
    fn check_packages(&self) {
        for package in &self.packages {
            let roles_count = package.roles.len();
            let (max_players_count, pattern_name) = package
                .patterns
                .iter()
                .max_by(|x, y| x.identity_list.len().cmp(&y.identity_list.len()))
                .map(|pattern| (pattern.identity_list.len(), pattern.name.as_str()))
                .unwrap();

            if roles_count < max_players_count {
                panic!(
                    "invalid package \"{}\" because roles count \"{}\" is less than max players count \"{}\" in pattern \"{}\"",
                    package.name,
                    roles_count,
                    max_players_count,
                    pattern_name
                );
            }
        }
    }

    /// 从 Provider 创建 Loader
    pub fn from_provider<T>(provider: T) -> Self
    where
        T: Provide,
    {
        let mut loader = Self::new();
        loader.add_provider(provider);

        loader
    }

    /// 从多个 Provider 创建 Loader
    pub fn from_providers<T>(providers: T) -> Self
    where
        T: IntoIterator,
        T::Item: Provide,
    {
        let mut loader = Self::new();
        loader.add_providers(providers);
        loader
    }

    /// 导入一个包
    pub fn add_package(&mut self, package: Package) -> &mut Self {
        self.packages.push(package);
        self.check_packages();
        self
    }

    /// 导入多个包
    pub fn add_packages<T>(&mut self, packages: T) -> &mut Self
    where
        T: IntoIterator<Item = Package>,
    {
        packages.into_iter().for_each(|package| {
            self.add_package(package);
        });
        self
    }

    /// 导入一个包
    pub fn add_provider<T>(&mut self, provider: T) -> &mut Self
    where
        T: Provide,
    {
        self.packages.push(provider.provide_package());
        self.check_packages();
        self
    }

    /// 导入多个包
    pub fn add_providers<T>(&mut self, providers: T) -> &mut Self
    where
        T: IntoIterator,
        T::Item: Provide,
    {
        providers.into_iter().for_each(|provider| {
            self.add_provider(provider);
        });
        self
    }

    /// 通过运行包的编号获取 Package 的引用
    pub fn select_package(&self, index: usize) -> Result<&Package, PackageNotFoundError> {
        match self.packages.get(index) {
            Some(package) => Ok(package),
            None => Err(PackageNotFoundError { index }),
        }
    }
}
